<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <!-- 引入element-ui样式文件 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <title>texthtml2pdf</title>
    <style>
        .exportBtn {
            position: relative;
            top: 35px;
            text-align: right;
        }

        .content {
            text-align: center;
            font-size: 23px;
        }

        .text {
            font-size: 10px;
            text-align: left;
        }

        .textTitle {
            font-size: 18px;
            margin-bottom: 10px;
        }


        .clearfix:before,
        .clearfix:after {
            display: table;
            content: "";
        }

        .clearfix:after {
            clear: both
        }

        .box-card {
            width: 100%;
            margin-top: 5px;
        }

        .el-card__header {
            text-align: left;
        }

        .caption {
            font-size: 16px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div id="pdfDom">
            <div class="exportBtn">
                <!-- 文本html导出pdf使用说明2：加入data-html2canvas-ignore属性，在导出pdf时，会忽略有该属性的dom -->
                <el-button type="primary" v-on:click="getPdf('#pdfDom')" :loading="loading" data-html2canvas-ignore>Export</el-button>
            </div>
            <div class="content">
                <div>
                    <span>韩信的简介</span>
                </div>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
                <el-card class="box-card">
                    <div slot="header" class="clearfix">
                        <span><strong>韩信</strong></span><span class="caption">（汉初三杰之一）</span>
                    </div>
                    <div class="text item">
                        韩信（－前196年），汉族，淮阴（原江苏省淮阴县，今淮安市淮阴区）人。西汉开国功臣，军事家，兵家四圣之一，汉初三杰之一 [1] ，中国军事思想“兵权谋家”的代表人物，被后人奉为“兵仙”、“神帅”。 [2]
                        秦末参加反秦斗争投奔项梁、项羽，却得不到任用。不得已转投刘邦，经夏侯婴推荐拜治粟都尉， [3] 后经萧何保举拜为大将， [4] 而韩信也为刘邦制定了汉中对策。
                        刘邦彭城兵败后，韩信先破楚军于京、索之间，后又平定了魏国。 [5] 之后请命北伐拿下代国，在刘邦派人收取其精兵后 [6] 背水一战击败赵国， [7] 同时派人降服了燕国。 [8] 之后派兵支援刘邦以及清除项羽派往赵国的楚骑兵，平定剩下的赵国城邑。 [9] 刘邦成皋兵败后夺去韩信兵马命其拿下齐国， [10] 之后韩信攻下临淄，并在潍水全歼龙且率领援齐的二十万楚军。 [11] 韩信开始进攻楚国，项羽被迫与刘邦签订鸿沟协议。
                        [12]
                        刘邦听从张良、陈平的计策撕毁鸿沟协议追击项羽 [13] 反被项羽击败。 [14] 汉五年，韩信会师垓下，围歼楚军，项羽自刎。
                        项羽死后解除兵权，徙为楚王，之后被人诬告贬为淮阴侯。 [15] 后吕后与萧何合谋， [16] 将其骗入长乐宫中，斩于钟室，夷其三族。 [17]
                        “国士无双”、“功高无二，略不世出”是楚汉之时人们对其的评价。作为统帅，他擒魏、取代、破赵、胁燕、东击齐，南灭楚垓下，名闻海内，威震天下；作为军事理论家，他与张良整理兵书、序次兵法，并著有《韩信》兵法三篇 。 [18]
                    </div>
                </el-card>
            </div>
        </div>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
    <script src="https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js"></script>

    <script>
        new Vue({
            el: '#app',

            data: function () {
                return {
                    loading: false
                }
            },

            methods: {
                getPdf: function (pdfDom) {
                    var that = this;
                    // 文本html导出pdf使用说明1：开始导出时，loading初始化为true,默认为false
                    that.loading = true;
                    var w = document.querySelector(pdfDom).offsetWidth; // 获得该容器的宽(包含进度条部分宽度)
                    var h = document.querySelector(pdfDom).offsetHeight; // 获得该容器的高(包含进度条部分宽度)
                    var scale = 2; // 定义缩放倍数
                    var canvas = document.createElement("canvas"); // 定义画布canvas

                    // 文本html导出pdf使用说明3：PDF内容失真处理
                    canvas.width = w * scale; // 将画布宽&&高放大两倍
                    canvas.height = h * scale;
                    canvas.state = false;
                    canvas.getContext("2d").scale(scale, scale);
                    var options = {
                        scale: scale,
                        canvas: canvas,
                        width: w,
                        height: h,
                        background: "#ffffff" // 背景设置为白色
                    };

                    html2canvas(document.querySelector(pdfDom), options).then(function (canvas) {
                            // 文本html导出pdf使用说明4：pdf页面间距调整
                            var a4Width = 552.28; // A4纸原始宽度为592.28，这里减去了左右间距2个20
                            var a4Height = 801.89; // A4纸原始高度为841.89，这里减去了左右间距2个20
                            var a4HeightRef = Math.floor(canvas.width / a4Width * a4Height); // html页面在a4纸中的高度 ,这里向下取整，后面与这个变量相关的值都是近似值，肯能会导致部分内容被分成2半，解决办法是在pdfDom加上一定的paddding。
                            var pageData = canvas.toDataURL('image/jpeg', 1.0);
                            var leftHeight = canvas.height; // html页面在canvas中的高度
                            var positionHeight = 0; // canvas分页，位置高度
                            var pdf = new jsPDF('x', 'pt', 'a4');
                            var currentCanvas = document.createElement('canvas'); // 遍历canvas，每一页生成的临时canvas
                            var height; // canvas分页，每页实际分割的高度(如果每页没有空白，该高度=a4HeightRef，有空白的，会将下面的空白高度去掉)

                            // 文本html导出pdf使用说明5：内容分割处理
                            function createImpl(canvas) {
                                if (leftHeight > 0) {
                                    var checkCount = 0; //统计出现空白的次数，按照每页像素点去从下到上，从左到右去遍历，这里根据实际PDF的内容，灵活调整阈值，使其分割更为合理(这里的阈值为10)

                                    if (leftHeight > a4HeightRef) {
                                        var currentHeight = positionHeight + a4HeightRef; // 遍历canvas当前高度=原始已经遍历的高度 + html在a4纸中的高度

                                        for (var i = currentHeight; i >= positionHeight; --i) {
                                            var isWrite = true;

                                            for (var j = 0; j < canvas.width; ++j) {
                                                var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data; //获取横轴为j，纵轴为i，高度宽度均为1的像素数据[255,255,255,1]

                                                if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) { // 判断当前像素矩阵数据是前3个数字是否为255，255，255
                                                    isWrite = false;
                                                    break;
                                                }
                                            }

                                            if (isWrite) {
                                                checkCount++;
                                                if (checkCount >= 10) { //  连续出现10个像素点，就跳出循环，获得每页实际分割的高度。这里建议页面内容与内容之间部分，建议背景用白色#ffffff，便于页面分割。当然统一用其他颜色也行。
                                                    currentHeight = i;
                                                    break;
                                                }
                                            } else {
                                                checkCount++;
                                            }
                                        }

                                        height = Math.round(currentHeight - positionHeight);
                                    } else {
                                        height = leftHeight;
                                    }

                                    currentCanvas.width = canvas.width;
                                    currentCanvas.height = height;
                                    // 将当前遍历的canvas页内容复制到新的currentCanvas中
                                    currentCanvas.getContext('2d').drawImage(canvas, 0, positionHeight, canvas.width, height, 0, 0, canvas.width, height);
                                    pdf.addPage();
                                    // 将currentCanvas添加到页面中
                                    pdf.addImage(currentCanvas.toDataURL('image/jpeg', 1.0), 'JPEG', 20, 20, a4Width, a4Width / currentCanvas.width * height);
                                    leftHeight -= height;
                                    positionHeight += height;

                                    if (leftHeight > 0) {
                                        createImpl(canvas);
                                    } else {
                                        pdf.save("export.pdf");
                                        canvas.state = true;
                                    }
                                }
                            }

                            //当内容未超过pdf一页显示的范围，无需分页
                            if (leftHeight < a4HeightRef) {
                                pdf.addImage(pageData, 'JPEG', 20, 20, a4Width, a4Width / canvas.width * leftHeight);
                                pdf.save("export.pdf");
                                canvas.state = true;
                            } else {
                                try {
                                    // 删除第一张空白页
                                    pdf.deletePage(1);
                                    createImpl(canvas);

                                } catch (err) {
                                    canvas.state = false;
                                }
                            }
                        })
                        .then(function () {
                            if (canvas.state) {
                                that.loading = false;
                            } else {
                                that.$message({
                                    message: "Error exporting pdf",
                                    type: "error"
                                });
                            }
                        });
                }
            }
        });
    </script>
</body>

</html>